package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.mq.config.MqConst;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 李旭
 * @Time: 9:43
 * @Description:
 */
@Service
@SuppressWarnings("all")
public class OrderInfoServiceImpl implements OrderInfoService {


    @Value("${ware.url}")
    private String wareUrl;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CartInfoMapper cartInfoMapper;

    //校验是否有库存 有货
    @Override
    public boolean hasStock(Long skuId, Integer skuNum) {
        //有货：  实际库存-锁定库存 >= 购买的数量
        //无货：  实际库存-锁定库存 < 购买的数量
        //无法使用feign
        //HttpClient 是Apache公司开的 Java包
        //windows10 hosts 配置   www.gware.com
        return "1".equals(HttpClientUtil.doGet(
                wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum));
    }


    //保存订单
    @Override
    @Transactional
    public Long saveOrder(OrderInfo orderInfo) {
        //1:订单表    订单主表

        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //订单交易编号  重复
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述 （支付原因）
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        for (OrderDetail orderDetail : orderDetailList) {
            sb.append(orderDetail.getSkuName()).append(" ");
            //重新查询商品清单的金额
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
        }
        if (sb.length() > 100) {
            orderInfo.setTradeBody(sb.toString().substring(0, 100));
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //失效时间  2小时
        calendar.add(Calendar.HOUR, 2);
        orderInfo.setExpireTime(calendar.getTime());
        //进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //总金额 （重新计算）
        orderInfo.sumTotalAmount();
        //保存订单
        orderInfoMapper.insert(orderInfo);//返回ID值
        //数组 ID
        List<String> skuIdList = new ArrayList<>(orderDetailList.size());
        //2:订单详情表    商品清单
        orderDetailList.forEach(orderDetail -> {
            //订单主表的ID
            orderDetail.setOrderId(orderInfo.getId());
            skuIdList.add(String.valueOf(orderDetail.getSkuId()));
            //保存订单详情
            orderDetailMapper.insert(orderDetail);
        });
        //3:删除购物车中已经购买了商品
        // delete from  cart_info where user_id = ? and  sku_id in (1,2,3,4)
/*        QueryWrapper queryWrapper = new QueryWrapper<CartInfo>();
        queryWrapper.eq("user_id",orderInfo.getUserId());
        queryWrapper.in("sku_id",skuIdList);
        cartInfoMapper.delete(queryWrapper);

        String cacheKey = RedisConst.USER_KEY_PREFIX +
                orderInfo.getUserId() + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheKey, skuIdList.toArray());*/
        //4:MQ延迟消息 完成  订单过期后的取消操作
     /*   rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),15);*/
        return orderInfo.getId();
    }

    //取消订单
    @Override
    public void cancelOrder(Long orderId) {
        //1:查询订单  只能未支付状态 才会取消订单 其它状态不取消

        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(null != orderInfo &&
                orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
            //发消息MQ 通知支付微服务
            //关闭支付宝的交易
            //alipay.trade.close	统一收单交易关闭接口
            //取消订单
            System.out.println("取消订单成功");
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);
        }
    }

    //只查询订单主表
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }
    //查询订单主表同时查询订单详情表
    public OrderInfo getOrderInfoAndOrderDetailList(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(null != orderInfo){
            orderInfo.setOrderDetailList(orderDetailMapper.
                    selectList(new QueryWrapper<OrderDetail>()
             .eq("order_id",orderId)));
        }
        return orderInfo;
    }
    //更新订单
    @Override
    public void updateOrder(Long orderId) {
        //幂等性问题
        OrderInfo orderInfo = getOrderInfo(orderId);
        if(null != orderInfo && orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
            //改为已支付
            orderInfo.setOrderStatus(OrderStatus.PAID.name());
            //进度状态已支付
            orderInfo.setProcessStatus(ProcessStatus.PAID.name());
            //更新订单
            orderInfoMapper.updateById(orderInfo);
        }
    }

    //发消息给库存系统
    @Override
    public void sendOrderStatus(Long orderId) {
        //幂等性问题
        OrderInfo orderInfo = getOrderInfo(orderId);
        if(null != orderInfo && orderInfo.getOrderStatus().equals(OrderStatus.PAID.name())){
            //进度状态从已支付改为通知仓库
            orderInfo.setProcessStatus(ProcessStatus.NOTIFIED_WARE.name());
            //更新订单
            orderInfoMapper.updateById(orderInfo);
            //发消息 给 库存系统
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                    MqConst.ROUTING_WARE_STOCK,initWareOrder(orderId));
        }

    }

    //开始拆单
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {

        List<OrderInfo> orderInfoList = new ArrayList<>();
        //wareSkuMap :  [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        //原理： 1张订单由于仓库不在一起 变成多张订单
        //原订单 父亲订单
        OrderInfo originOrderInfo = getOrderInfoAndOrderDetailList(orderId);
        //新订单 子订单
        List<Map> listMap = JSONObject.parseArray(wareSkuMap, Map.class);
        //Map :{"wareId":"1","skuIds":["2","10"]}    子订单
        //Map :{"wareId":"2","skuIds":["3"]}         子订单
        for (Map map : listMap) {
            //子订单    子订单与父订单之间 ID不同  金额不同  (子订单有父ID  父订单没有NULL)
            OrderInfo subOrderInfo = new OrderInfo();
            //所有成员变量全部复制一份
            BeanUtils.copyProperties(originOrderInfo,subOrderInfo);
            //子订单ID
            subOrderInfo.setId(null);
            //子订单有父ID
            subOrderInfo.setParentOrderId(originOrderInfo.getId());
            //仓库ID
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));

            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            //订单详情表
            List<OrderDetail> orderDetailList = originOrderInfo.getOrderDetailList();
            //Map :{"wareId":"1","skuIds":["2","10"]}    子订单
            //Map :{"wareId":"2","skuIds":["3"]}         子订单
            List<String> skuIds = (List<String>) map.get("skuIds");
            for (OrderDetail orderDetail : orderDetailList) {
                for (String skuId : skuIds) {
                    if(orderDetail.getSkuId().equals(Long.parseLong(skuId))){
                        subOrderDetailList.add(orderDetail);
                        break;
                    }
                }
            }
            //子订单有了自己的子订单详情集合
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //新的子订单总金额
            subOrderInfo.sumTotalAmount();

            //添加一个子订单
            orderInfoList.add(subOrderInfo);
            //保存订单主表
            orderInfoMapper.insert(subOrderInfo);
            //修改订单详情表
            subOrderDetailList.forEach(subOrderDetail -> {
                //外键
                subOrderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(subOrderDetail);
            });
        }
        //修改原订单的订单状态为已拆单
        originOrderInfo.setOrderStatus(OrderStatus.SPLIT.name());
        originOrderInfo.setProcessStatus(ProcessStatus.SPLIT.name());
        orderInfoMapper.updateById(originOrderInfo);
        return orderInfoList;
    }
    public Map initWareOrder(OrderInfo orderInfo){
        Map map = new HashMap<>();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        map.put("paymentWay",
                "ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        //仓库的ID
        map.put("wareId",orderInfo.getWareId());

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<Map> listMap = orderDetailList.stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId",orderDetail.getSkuId());
            m.put("skuName",orderDetail.getSkuName());
            m.put("skuNum",orderDetail.getSkuNum());
            return m;
        }).collect(Collectors.toList());
        map.put("details",listMap);
        return map;
    }

    //构建库存微服务所需要的数据
    public String initWareOrder(Long orderId){
        OrderInfo orderInfo = getOrderInfoAndOrderDetailList(orderId);
        Map map = new HashMap<>();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        map.put("paymentWay",
                "ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<Map> listMap = orderDetailList.stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId",orderDetail.getSkuId());
            m.put("skuName",orderDetail.getSkuName());
            m.put("skuNum",orderDetail.getSkuNum());
            return m;
        }).collect(Collectors.toList());
        map.put("details",listMap);
        return JSONObject.toJSONString(map);
    }


    //更新订单状态
    @Override
    public void updateOrder(String orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(Long.parseLong(orderId));
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    @Autowired
    private RabbitService rabbitService;
}
